Kotlin Extension — Properties&Companion

Kotlin Extension — Properties&Companion

方法可以有装饰者模式,那属性呢?
当然可以!

实例属性

考虑实例属性的这样一个例子:

在Parent.kt中声明一个value的变量并赋值为1,并在Other.kt中使用Properties Extension
1
2
3
class Parent {
val value : Int = 1
}
1
2
3
4
class Other

val Parent.value : Int
get() = 0
经过kotlinc的编译(编译过程中同样会有warning),反编译OtherKt.class 文件:
1
2
3
4
5
6
7
8
9
10
Compiled from "Other.kt"
public final class com.maxtropy.viewtest.OtherKt {
public static final int getValue(com.maxtropy.viewtest.Parent);
Code:
0: aload_0
1: ldc #9 // String $receiver
3: invokestatic #15 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
6: iconst_0
7: ireturn
}

哇!OtherKt中多了一个getValue()方法诶!他在唯一入参是Parent,这意味着:

  • 后面如果在kt文件中访问Parent实例的value变量,最终都是访问的这个方法!
  • 在同一个Other.kt中,对同一个类的同一个属性,只能使用一次Extension (用两次还没编译呢,IDE就直接先报Error了靓仔!)

Companion Object

同样跟上面的例子,只不过我们将value声明在Parent的companion object中,在Other中执行Parent.Companion.value的Extension

1
2
val Parent.Companion.value
get() = 99

编译结果跟普通的Properties Extension近乎一致:

1
2
3
4
5
6
7
8
9
10
Compiled from "Other.kt"
public final class com.maxtropy.viewtest.OtherKt {
public static final int getValue(com.maxtropy.viewtest.Parent$Companion);
Code:
0: aload_0
1: ldc #9 // String $receiver
3: invokestatic #15 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
6: bipush 99
8: ireturn
}

最大的区别便是唯一入参类型变成了Parent$Companion
值得我们注意的是,最后入栈的常量(代码中最后返回的常量数)并不像上面是一个int型常量,而是一个byte型常量。想必是kotlinc在编译过程中自动优化了